/*
 * Copyright (c) 2016. For Intelligent Group.
 */

package com.intelligent.mts.da.server;

import com.intelligent.mts.common.utils.StringUtils;
import com.intelligent.mts.da.handler.ProtocolAdapterHandler;
import com.intelligent.mts.da.utils.SystemConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by Julia.Zhou on 2016/07/20.
 */
public class MtsServer {

    public static Logger logger = LoggerFactory.getLogger(MtsServer.class);

    private static String SERVER_IP = "localhost";
    private static int SERVER_PORT = 8888;

    public void launch() {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:spring/spring*.xml");
        Integer port = context.getBean(SystemConfig.class).getServerPort();
        String ip = context.getBean(SystemConfig.class).getServerIp();
        if (StringUtils.isNotBlank(ip)) {
            SERVER_IP = context.getBean(SystemConfig.class).getServerIp();
        }

        if (port != null) {
            SERVER_PORT = context.getBean(SystemConfig.class).getServerPort();
        }
    }

    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();

    protected void run() {

        try {
            logger.info("Starting DA server...");
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup);
            b.channel(NioServerSocketChannel.class);
            //b.option(ChannelOption.SO_BACKLOG, 100);
            //b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000);
            b.option(ChannelOption.SO_KEEPALIVE, true);
//            b.handler(new LoggingHandler(LogLevel.INFO));

            b.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    ChannelPipeline pipeline = socketChannel.pipeline();
                    pipeline.addLast("ProtocolAdapterHandler",new ProtocolAdapterHandler());
                }
            });

            ChannelFuture f = b.bind(SERVER_IP, SERVER_PORT).sync();
            logger.info("Binding ip:{}, port:{}.", SERVER_IP, SERVER_PORT);
            logger.info("Server started.");
            f.channel().closeFuture().sync();
        } catch (Exception e) {
            logger.error("Unexpected exception from server " + e.getMessage());
            e.printStackTrace();
        } finally {
            this.shutdown();
        }
    }

    private void shutdown() {
        // Shut down all event loops to terminate all threads.
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
    }

    public static void main(String[] args) {
        try {
            MtsServer server = new MtsServer();
            server.launch();
            server.run();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
